// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2004-11-16

#ifndef __DB_COMMAND_H_COMMON_SVR_BASE__
#define __DB_COMMAND_H_COMMON_SVR_BASE__

#pragma once

#include "base_log.h"

namespace JoyServer
{

#ifdef _DEBUG

#   define JOY_DB_VALIDATE_PARAM(nParam) \
    if(nParam > __super::GetParamCount())\
    {\
        JOY_LOG_DB("param count is<%d> but current index is<%d> for command <%s>.",\
            __super::GetParamCount(), nParam, (PCSTR)GetCommandTextA());\
        return false;\
    }

#else

#   define JOY_DB_VALIDATE_PARAM __noop

#endif

class CJoyDbCommand : public 
    CCommand<CDynamicParameterAccessor, CRowset, CMultipleResults>
{
protected:
    CStringW m_commandText;
    void* m_dummy;

public:
    DBROWCOUNT m_affectRows;
public:
    CJoyDbCommand()
    {
        m_dummy = NULL;
        m_affectRows = 0;
    }

    bool Create(const ATL::CSession& sess, PCWSTR wszCommand);
    bool Open(bool doLog = true);
    bool Open(LONG& affectedRows, bool doLog = true);

    CString GetCommandTextA()
    {
        return CString(m_commandText);
    }

    template<typename DataType>
    bool GetParam(DBORDINAL nParam, DataType& data)
    {
        JOY_DB_VALIDATE_PARAM(nParam);
        if(!__super::GetParam(nParam, &data))
        {
            JOY_LOG_DB("failed get param<%d>'s value for command <%s>.", nParam, (PCSTR)GetCommandTextA());
            return false;
        }
        return true;
    }
    bool GetParam(DBORDINAL nParam, CString& data)
    {
        JOY_DB_VALIDATE_PARAM(nParam);
        if(!__super::GetParamString(nParam, data))
        {
            JOY_LOG_DB("failed get param<%d>'s value for command <%s>.", nParam, (PCSTR)GetCommandTextA());
            return false;
        }
        return true;
    }

    template<typename DataType>
    bool SetParam(DBORDINAL nParam, const DataType& data)
    {
        JOY_DB_VALIDATE_PARAM(nParam);
        if(!__super::SetParam(nParam, &data))
        {
            JOY_LOG_DB("failed set param<%d>'s value for command <%s>.", nParam, (PCSTR)GetCommandTextA());
            return false;
        }
        return true;
    }

    bool SetParam(DBORDINAL nParam, PCSTR data)
    {
        JOY_DB_VALIDATE_PARAM(nParam);
        if(!__super::SetParamString(nParam, data))
        {
            JOY_LOG_DB("failed set param<%d>'s value for command <%s>.", nParam, (PCSTR)GetCommandTextA());
            return false;
        }
        return true;
    }

    bool SetParam(DBORDINAL nParam, const CString& data)
    {
        return SetParam(nParam, (PCSTR)data);
    }

    // set varbinary parameters.
	bool SetParam(DBORDINAL nParam, const void* pData, int nLen, DBSTATUS status = DBSTATUS_S_OK ) throw();

    void GetValue(PCSTR colName, CString& strValue);
    void GetValue(DBORDINAL nCol, CString& strValue);
    bool GetBoolean(PCSTR colName, bool& b)
    {
        UINT n = 0;
        bool r = GetValue(colName, n);
        b = (n!=0);
        return r;
    }

    template<typename T>
    bool GetValue(PCSTR colName, T& v)
    {
        return __super::GetValue(colName, &v);
    }
    template<typename T>
    bool GetValue(DBORDINAL nCol, T& v)
    {
        return __super::GetValue(nCol, &v);
    }

    HRESULT GetNextResult()
    {
        HRESULT hr = __super::GetNextResult(&m_affectRows);
        return hr;
    }

    bool IgnoreParam(DBORDINAL nParam);

    void PrepareOutput();
    HRESULT MoveNext() throw()
	{
        if(m_spRowset != NULL)
        {
            return __super::MoveNext();
        }
        return -1;
	}

};

inline bool HasMoreRow(HRESULT hr)
{
    return (hr != DB_S_ENDOFROWSET)&&SUCCEEDED(hr);
}

} // namespace JoyServer

#endif  // __DB_COMMAND_H_COMMON_SVR_BASE__